#include"2cache.h"

// Cache类的构造函数，初始化缓存参数
Cache::Cache(unsigned blockSize, unsigned size, unsigned assoc, Cache* nextLevel, unsigned vicSize, string file){
    this->blockSize = blockSize;  // 块大小
    this->size = size;            // 缓存总大小
    this->assoc = assoc;          // 相联度
    this->nextLevel = nextLevel;  // 指向下一级缓存的指针
    this->trace_file = file;      // 追踪文件名
    
    // 初始化cache_set，根据缓存大小、块大小和相联度确定组的数量
    cache_set.resize(size / (blockSize * assoc)); 
    for(unsigned i = 0; i < cache_set.size(); i++)  
        cache_set[i].resize(assoc);  // 每组中有assoc个缓存块
    // 如果受害者缓存不为空，则初始化受害者缓存的大小
    if(vicSize) 
        vic_cache.resize(vicSize / blockSize);  
    // 初始化缓存的统计信息
    totalReads = missReads = totalWrites = missWrites = swap = writeBack = 0;
}

// 缓存模拟的运行函数，从trace文件中读取地址并进行操作
void Cache::Run(){
    ifstream file_path("../traces/" + trace_file);  // 打开trace文件
    string mid;
    while(getline(file_path, mid)){
        char r_or_w;            // 记录操作是读还是写
        unsigned address;       // 操作的内存地址
        istringstream is(mid);  
        is >> r_or_w;           // 读取操作类型
        is >> hex >> address;   // 读取操作地址
        Visit(address, r_or_w); // 访问地址并处理操作
    }
    file_path.close();
    PrintResult();              // 输出结果
}

// 地址转换函数，将内存地址分解为tag和index
tag_index Cache::Addr_translation(unsigned address){
    unsigned tag = address / (blockSize * cache_set.size());  
    unsigned index = (address ^ (tag * blockSize * cache_set.size())) / blockSize;  
    return tag_index(tag, index);  // 返回地址中的tag和index
}

// 访问缓存函数，根据地址和操作类型处理缓存访问
void Cache::Visit(unsigned address, char op){
    tag_index add = Addr_translation(address); // 将地址分解为tag和index
    op == 'r' ? totalReads++ : totalWrites++;  // 根据操作类型更新读写计数
    // 遍历该index对应的缓存块，查找是否有有效块且tag匹配
    for(unsigned i = 0; i < cache_set[add.second].size(); i++) 
        if(cache_set[add.second][i].valid && cache_set[add.second][i].tag == add.first){  
            unsigned find_countBlock = cache_set[add.second][i].countBlock;
            vector<Block>::iterator mid;
            // 更新其他缓存块的LRU计数
            for(mid = cache_set[add.second].begin(); mid != cache_set[add.second].end(); mid++)
                mid->countBlock += (mid->valid && mid->countBlock < find_countBlock);  
            cache_set[add.second][i].countBlock = 0;  // 将访问的缓存块的计数器置0
            cache_set[add.second][i].dirty |= (op == 'w'); // 如果是写操作，设置脏位
            return;
        }
    // 如果在受害者缓存中找到匹配项
    vector<Block>::iterator victim;
    for(victim = vic_cache.begin();victim != vic_cache.end();victim++)
        if(victim->valid && victim->tag == address / blockSize)
            break;
    if(victim != vic_cache.end()){  // 如果找到了匹配的块
        vector<Block>::iterator L1_abandon = max_element(cache_set[add.second].begin(), cache_set[add.second].end());  
        // 更新LRU计数
        for(unsigned i = 0; i < cache_set[add.second].size(); i++)
            cache_set[add.second][i].countBlock++;  
        for(unsigned i = 0; i < vic_cache.size(); i++) 
            if(vic_cache[i].countBlock < victim->countBlock) 
                vic_cache[i].countBlock++;  
        bool victim_dirty = victim->dirty;
        *victim = {0, L1_abandon->tag * (unsigned)cache_set.size() + add.second, L1_abandon->dirty, true};  
        *L1_abandon = {0, add.first, op == 'w' || victim_dirty, true};  // 替换缓存块
        swap++;  // 增加swap计数
        return;
    }
    // 如果没有在缓存或受害者缓存中找到匹配项，则执行替换
    Replace(address, op);
}

// 缓存替换函数
void Cache::Replace(unsigned address, char op){
    tag_index add = Addr_translation(address);  // 地址转换
    op == 'r' ? missReads++ : missWrites++;  // 更新读写缺失计数
    vector<Block>::iterator L1_ababdon;
    // 如果找到无效块则直接替换
    for(L1_ababdon = cache_set[add.second].begin(); L1_ababdon != cache_set[add.second].end(); L1_ababdon++)  
        if(!L1_ababdon->valid)
            break;
    // 如果所有块都有效，找到最近最少使用的块进行替换
    if(L1_ababdon == cache_set[add.second].end())  
        L1_ababdon = max_element(cache_set[add.second].begin(), cache_set[add.second].end());
    Block L1_abandon_info = *L1_ababdon;
    for(unsigned i = 0; i < cache_set[add.second].size(); i++)
        cache_set[add.second][i].countBlock++;  // 更新LRU计数
    *L1_ababdon = {0, add.first, op == 'w', true};  // 更新替换的缓存块
    if(L1_abandon_info.valid){  // 如果被替换的块是有效的
        // 处理受害者缓存
        if(vic_cache.size()){  
            vector<Block>::iterator victim_abandon;
            for(victim_abandon = vic_cache.begin();victim_abandon != vic_cache.end();victim_abandon++) 
                if(!victim_abandon->valid)
                    break;
            if(victim_abandon == vic_cache.end())
                victim_abandon = max_element(vic_cache.begin(), vic_cache.end());
            Block victim_abandon_info = *victim_abandon;
            for(unsigned i = 0; i < vic_cache.size(); i++)
                vic_cache[i].countBlock++;  
            *victim_abandon = {0, L1_abandon_info.tag * (unsigned)cache_set.size() + add.second, L1_abandon_info.dirty, true};  
            // 如果受害者缓存中的块是脏的，进行写回
            if(victim_abandon_info.dirty){  
                writeBack++;
                if(nextLevel)  
                    nextLevel->Visit(victim_abandon_info.tag * blockSize, 'w');  
            }
        }
        // 如果L1块是脏的，写回到下一级缓存
        else if(L1_abandon_info.dirty){  
            if(nextLevel)  
                nextLevel->Visit((L1_abandon_info.tag * cache_set.size() + add.second) * blockSize, 'w');
            else  
                writeBack++;
        }
    }
    if(nextLevel)  // 访问下一级缓存
        nextLevel->Visit(address, 'r');
}

// 输出模拟结果函数
void Cache::PrintResult(){
    cout << setiosflags(ios::left);
    cout << "===== Simulator configuration =====\n";
    cout << setw(30) << "BLOCKSIZE:" << blockSize << endl;
    cout << setw(30) << "L1_SIZE:" << size << endl;
    cout << setw(30) << "L1_ASSOC:" << assoc << endl;
    cout << setw(30) << "Victim_Cache_SIZE:" << vic_cache.size() * blockSize << endl;
    cout << setw(30) << "L2_SIZE:" << (nextLevel ? nextLevel->size : 0) << endl;
    cout << setw(30) << "L2_ASSOC:" << (nextLevel ? nextLevel->assoc : 0) << endl;
    cout << setw(30) << "trace_file:" << trace_file << endl;
    cout << "===================================" << endl;

    // 输出L1缓存的内容
    cout << "===== L1 contents =====" << endl;
    for(unsigned i = 0; i != cache_set.size(); i++){
        cout << "set " << i << ": ";
        vector<Block> mid = cache_set[i];
        stable_sort(mid.begin(), mid.end());
        for(unsigned j = 0; j < mid.size(); j++)
            cout << hex << mid[j].tag << (mid[j].dirty ? " D  " : "    ");
        cout << endl << dec;
    }

    // 如果受害者缓存不为空，输出受害者缓存的内容
    if(vic_cache.size()){
        cout << "===== Victim Cache contents =====" << endl;
        cout << "set 0: ";
        stable_sort(vic_cache.begin(), vic_cache.end());
        for(unsigned i = 0; i < vic_cache.size(); i++)
            cout << hex << vic_cache[i].tag << (vic_cache[i].dirty ? " D  " : "    ");
        cout << endl << dec;
    }

    // 如果有下一级缓存，输出L2缓存的内容
    if(nextLevel){
        cout << "===== L2 contents =====" << endl;
        for(unsigned i = 0; i != nextLevel->cache_set.size(); i++){
            cout << "set " << i << ": ";
            vector<Block> mid = nextLevel->cache_set[i];
            stable_sort(mid.begin(), mid.end());
            for(unsigned j = 0; j < mid.size(); j++)
                cout << hex << mid[j].tag << (mid[j].dirty ? " D  " : "    ");
            cout << endl << dec;
        }
    } 

    // 计算模拟结果
    float MR1, MR2, HT1, HT2, MP;
    MR1 = (missReads + missWrites) / (float)(totalReads + totalWrites);
    MR2 = (nextLevel ? nextLevel->missReads / (float)nextLevel->totalReads : 0);
    HT1 = 0.25 + 2.5 * (size / (512.0 * 1024)) + 0.025 * (blockSize / 16.0) + 0.025 * assoc;
    HT2 = nextLevel ? 2.5 + 2.5 * (nextLevel->size / (512.0 * 1024)) + 0.025 * (nextLevel->blockSize / 16.0) + 0.025 * nextLevel->assoc : 0;
    MP = 20 + 0.5 * ((nextLevel ? nextLevel->blockSize : blockSize) / 16.0);
    unsigned MT = (nextLevel ? nextLevel->missReads + nextLevel->missWrites + nextLevel->writeBack : missReads + missWrites + writeBack);

    // 输出模拟结果的原始数据
    cout << "====== Simulation results (raw) ======" << endl;
    cout << setw(38) << "a. number of L1 reads:" << totalReads << endl;
    cout << setw(38) << "b. number of L1 read misses:" << missReads << endl;
    cout << setw(38) << "c. number of L1 writes:" << totalWrites << endl;
    cout << setw(38) << "d. number of L1 write misses:" << missWrites << endl;
    cout << setw(38) << "e. L1 miss rate:" << fixed << setprecision(4) << MR1 << endl;
    cout << setw(38) << "f. number of swaps:" << swap << endl;
    cout << setw(38) << "g. number of victim cache writeback:" << writeBack << endl;
    cout << setw(38) << "h. number of L2 reads:" << (nextLevel ? nextLevel->totalReads : 0) << endl;
    cout << setw(38) << "i. number of L2 read misses:" << (nextLevel ? nextLevel->missReads : 0) << endl;
    cout << setw(38) << "j. number of L2 writes:" << (nextLevel ? nextLevel->totalWrites : 0) << endl;
    cout << setw(38) << "k. number of L2 write misses:" << (nextLevel ? nextLevel->missWrites : 0) << endl;
    cout << setw(38) << "l. L2 miss rate:" << fixed << setprecision(nextLevel ? 4 : 0) << MR2 << endl;
    cout << setw(38) << "m. number of L2 writebacks:" << (nextLevel ? nextLevel->writeBack : 0) << endl;
    cout << setw(38) << "n. total memory traffic:" << MT << endl;

    // 输出模拟结果的性能分析
    cout << "==== Simulation results (performance) ====" << endl;
    cout << setw(32) << "1. average access time:" << setprecision(4) << HT1 + (MR1 * (nextLevel ? (HT2 + MR2 * MP) : MP)) << " ns" << endl;
}
